<?php
/**
 * Created by PhpStorm.
 * User: coolinmind
 * Date: 07/01/2019
 * Time: 12:04
 */

namespace App\Services\UCenter\UCenter;


use App\Models\Fund\IntegralAccount;
use App\Models\Fund\IntegralOptionLog;
use App\Models\UCenter\CompanyDriver;
use App\Models\UCenter\Payment;
use App\Models\UCenter\Signs;
use App\Models\User\User;
use App\Services\Setting\SettingIndex;
use App\Services\User\Token\TokenLogic;
use App\Services\User\Traits\Password;
use App\Traits\SmsTrait;
use Illuminate\Support\Facades\Redis;
use DB;

class UCenterLogic
{
    use Password;
    use SmsTrait;
    public function updateUserInfo($data)
    {
        $token = $data['token'];
        if(isset($data['other_info']))
            $data['other_info'] = json_encode($data['other_info']);
        unset($data['token']);
        $res = User::where('id', $data['id'])->update($data);
        $userInfo = User::with('provinceText', 'cityText', 'countyText')->where(['id' => $data['id']])->first()->toArray();
        if($userInfo['province_text'])
            $userInfo['province_text'] = json_encode($userInfo['province_text'], true);
        if($userInfo['city_text'])
            $userInfo['city_text'] = json_encode($userInfo['city_text'], true);
        if($userInfo['county_text'])
            $userInfo['county_text'] = json_encode($userInfo['county_text'], true);
        $res1 = $this->changeRedisInfo($token, $userInfo);
        return auto_return($res && $res1);
    }

    // 用户更改自己的登录密码
    public function editSelfLoginPassword(array $data): array
    {
        // 根据token找到用户的ID
        $tokenObj = new tokenLogic();
        $tokenRes = $tokenObj->hGetAll($data['token']);
        if(SUCCESS_STATUS !== $tokenRes['status']){
            return $tokenRes;
        } else if (!isset($tokenRes['res']['id'])) {
            return verify_err(null, '此token没有找到相关用户ID');
        }
        // 将相应信息发送给相关接口
        $newData = make_map($data, ['login_password', 'old_login_password', 're_login_password'], '');
        $newData['id'] = $tokenRes['res']['id'];
        $newData['update_login_pwd_time'] = NOW;
        $res = $this->editLoginPassword($newData);
        return $res;
//        return $res['status'] ? auto_success($res['res'], '用户更改自己的登录密码成功') :  auto_failure(null, '用户更改自己的登录密码失败');
    }

    // 修改登录密码
    public function editLoginPassword(array $data): array
    {
        // 验证登录密码
        $checkData = $data;
        $checkData['login_password'] = $data['old_login_password'];
        $checkRes = $this->checkLoginPassword($checkData);
        if(SUCCESS_STATUS !== $checkRes['status']){ return $checkRes; }
        // 修改登录密码
        $newData = $this->_makeLoginPassword($data['login_password']);
        isset($data['update_login_pwd_time']) && $newData['update_login_pwd_time'] = $data['update_login_pwd_time'];
        $_where = make_map($data, ['name','id','phone']);
        $_where['status'] = '1';
        $res = User::where($_where)->update($newData);
        return auto_return($res, '成功修改登录密码', '修改登录密码失败');
    }

    // 验证登录密码
    public function checkLoginPassword(array $data): array
    {
        // 查找用户信息
        $_where = make_map($data, ['name','id','phone']);
        $_where['status'] = '1';
        $info = User::where($_where)->select('login_password', 'login_salt')->first()->toArray();
        if(!$info){ return verify_err(null, '没有相关用户信息'); }
        // 验证登陆密码
        //dd($data['login_password'] ,  $info);
        $check = $this->_checkLoginPassword($data['login_password'],(array) $info);
        return auto_return($check, '登陆密码正确', '登陆密码错误');
    }

    // 用户更改自己的支付密码
    public function editSelfPayPassword(array $data): array
    {
        // 根据token找到用户的ID
        $tokenObj = new TokenLogic();
        $tokenRes = $tokenObj->hGetAll($data['token']);
        if(SUCCESS_STATUS !== $tokenRes['status']){
            return $tokenRes;
        } else if (!isset($tokenRes['res']['id'])) {
            return verify_err(null, '此token没有找到相关用户ID');
        }
        // 将相应信息发送给相关接口
        $newData = make_map($data, ['pay_password', 'old_pay_password', 're_pay_password'], '');
        $newData['id'] = $tokenRes['res']['id'];
        $newData['update_pay_pwd_time'] = NOW;
        $res = $this->editPayPassword($newData);
        return $res['status'] ? auto_success($res['res'], '用户更改自己的支付密码成功') :  auto_failure(null, '用户更改自己的支付密码失败:' . $res['msg']);
    }

    // 修改支付密码
    public function editPayPassword(array $data): array
    {
        // 验证支付密码
        $checkData = $data;
        $checkData['pay_password'] = $data['old_pay_password'];
        $checkRes = $this->checkPayPassword($checkData);
        if(SUCCESS_STATUS !== $checkRes['status']){ return $checkRes; }
        // 修改支付密码
        $newData = $this->_makePayPassword($data['pay_password']);
        isset($data['update_pay_pwd_time']) && $newData['update_pay_pwd_time'] = $data['update_pay_pwd_time'];
        $_where = make_map($data, ['name','id','phone']);
        $_where['status'] = '1';
        $res = User::where($_where)->update($newData);
        return auto_return($res, '成功修改支付密码', '修改支付密码失败');
    }

    // 验证支付密码
    public function checkPayPassword(array $data): array
    {
        // 查找用户信息
        $_where = make_map($data, ['name','id','phone']);
        $_where['status'] = '1';
        $info = User::select('pay_password','pay_salt')
            ->where($_where)
            ->first()
            ->toArray();
        if(!$info){
            return verify_err(null, '没有相关用户信息');
        }else if($info['pay_password'] === ''){
            return verify_err(null, '您还没有设置支付密码');
        }
        // 验证支付密码
        $check = $this->_checkPayPassword($data['pay_password'], $info);
        return auto_return($check, '支付密码正确', '支付密码错误');
    }

    //用户进行实名认证(个人信息)
    public function authentication(array $data): array
    {
        // 根据token找到用户的ID
        $tokenObj = new tokenLogic();
        $tokenRes = $tokenObj->hGetAll($data['token']);
        if(SUCCESS_STATUS !== $tokenRes['status']){
            return $tokenRes;
        } else if (!isset($tokenRes['res']['id'])) {
            return verify_err(null, '此token没有找到相关用户ID');
        }
        $user_info = User::where('id', $tokenRes['res']['id'])->first();
        $other_info = json_decode($user_info['other_info'], true);
        if(in_array($other_info['authen_status'], ['0','1'])){
            return verify_err(null, '您已提交过认证信息');
        }
        //将图片转化成文件
        $fontImg = $this->base64ToImg($data['front_id_photo'], 'identity');
        if($fontImg['status'] != SUCCESS_STATUS)
            return auto_failure($fontImg, '提交认证失败');
        $backImg = $this->base64ToImg($data['back_id_photo'], 'identity');
        if($backImg['status'] != SUCCESS_STATUS)
            return auto_failure($backImg, '提交认证失败');
        $fullImg = $this->base64ToImg($data['full_photo'], 'identity');
        if($fullImg['status'] != SUCCESS_STATUS)
            return auto_failure($fullImg, '提交认证失败');

        $authentication['front_id_photo'] = $fontImg['res']['path'];
        $authentication['back_id_photo'] = $backImg['res']['path'];
        $authentication['full_photo'] = $fullImg['res']['path'];

        $authentication['id'] = $data['id'];
        $authentication['create_time'] = NOW;
        $authentication['update_time'] = NOW;
        $authentication['authen_status'] = 0;  // 认证状态 -1 未提交 0 待审核 1 审核通过 2 审核失败
        $authentication['name'] = $data['name'];
//        $new_other_info['authentication'] = $authentication;
//        $new_other_info['authen_status'] = 0;  // 认证状态 -1 未提交 0 待审核 1 审核通过 2 审核失败
//        $new_other_info['name'] = $data['name'];
        $data['other_info'] = json_encode(array_merge($other_info, $authentication));
        $data['id'] = $tokenRes['res']['id'];
        $uMod = User::where('id', $tokenRes['res']['id'])->first();
        $uMod->other_info = $data['other_info'];
        $uMod->real_name = $data['name'];
        $res = $uMod->save();
        $userInfo = $uMod->toArray();
        $this->changeRedisInfo($data['token'], $uMod->toArray());
        return $res ?
            auto_success($res, '提交实名认证成功') :
            auto_failure(null, '提交实名认证失败');

    }

    // 企业进行实名认证
    public function corporateCertification(array $data): array
    {
        // 根据token找到用户的ID
        $tokenObj = new tokenLogic();
        $tokenRes = $tokenObj->hGetAll($data['token']);
        if(SUCCESS_STATUS !== $tokenRes['status']){
            return $tokenRes;
        } else if (!isset($tokenRes['res']['id'])) {
            return verify_err(null, '此token没有找到相关用户ID');
        }
        $user_info = User::where('id', $tokenRes['res']['id'])->first();
        $enterprise_info = json_decode($user_info['enterprise_info'], true);
        if(in_array($enterprise_info['authen_status'], ['0','1'])){
            return verify_err(null, '您已提交过认证信息');
        }
        //将图片转化成文件
        $fontImg = $this->base64ToImg($data['front_id_photo'], 'identity');
        if($fontImg['status'] != SUCCESS_STATUS)
            return auto_failure($fontImg, '提交认证失败');
        $backImg = $this->base64ToImg($data['back_id_photo'], 'identity');
        if($backImg['status'] != SUCCESS_STATUS)
            return auto_failure($backImg, '提交认证失败');
        $licenseImg = $this->base64ToImg($data['business_license'], 'identity');
        if($licenseImg['status'] != SUCCESS_STATUS)
            return auto_failure($licenseImg, '提交认证失败');

        $authentication['front_id_photo'] = $fontImg['res']['path'];
        $authentication['back_id_photo'] = $backImg['res']['path'];
        $authentication['business_license'] = $licenseImg['res']['path'];

        $authentication['mail'] = $data['mail'];
        $authentication['number'] = $data['number'];
        $authentication['address'] = $data['address'];
        $authentication['social_unified_coding'] = $data['social_unified_coding'];
        $authentication['province'] = $data['province'];
        $authentication['legal_person'] = $data['legal_person'];
        $authentication['create_time'] = NOW;
        $authentication['update_time'] = NOW;
        $authentication['authen_status'] = 0;  // 认证状态 -1 未提交 0 待审核 1 审核通过 2 审核失败
        $authentication['name'] = $data['name'];
        $data['enterprise_info'] = json_encode(array_merge($enterprise_info, $authentication));
        $data['id'] = $tokenRes['res']['id'];
        $uMod = User::where('id', $tokenRes['res']['id'])->first();
        $uMod->enterprise_info = $data['enterprise_info'];
        $res = $uMod->save();
        $this->changeRedisInfo($data['token'], $uMod->toArray());
        return $res ?
            auto_success($res, '提交实名认证成功') :
            auto_failure(null, '提交实名认证失败');

    }

    /**
     * 添加支付方式
     * @param $data
     * @return array
     */
    public function addPayment($data)
    {
        $data = make_map($data, ['name', 'type', 'user_id', 'account','bank_name','is_default']);
        $data['created_at'] = date('Y-m-d H:i:s', NOW);
        $data['updated_at'] = date('Y-m-d H:i:s', NOW);
        $res = Payment::insert($data);
        return $res ?
            auto_success($res, '添加成功') :
            auto_failure($res, '添加失败');
    }

    /**
     * 获取支付方式列表
     * @param $data
     * @return array
     */
    public function getPaymentList($data)
    {
        $res = Payment::where('user_id', $data['user_id'])->orderBy('is_default','desc')->get();
        return $res ?
            auto_success($res, '获取列表成功') :
            auto_failure($res, '获取列表失败');
    }

    /**
     * 根据id删除支付方式
     * @param $data
     * @return array
     */
    public function delPaymentById($data)
    {
        $res = Payment::where(['user_id' => $data['user_id'], 'id' => $data['id']])->delete();
        return $res ?
            auto_success($res, '删除成功'):
            auto_failure($res, '删除失败');
    }

    //用户上传头像
    public function upload($data)
    {
        $image = $data['file'];
        $userId = $data['user_id'];
        $uData = User::find($userId);
        $res = $this->base64ToImg($image);
        if($res['status'] != SUCCESS_STATUS)
            return auto_failure($res, '上传失败');
        //删除旧头像
        $oldFile = './'.ltrim($uData->head_portrait,'/');
        if(!empty($uData->head_portrait) && file_exists($oldFile)){
            unlink($oldFile);
        }

        try {
            $uData->head_portrait = $res['res']['path'];
            $r = $uData->save();
            //更新redis存储的用户信息
            $tokenObj = new TokenLogic();
            $userInfo = $uData->toArray();
            $updateTokenRes = $tokenObj->hMset(['token'=>$data['token'], 'arr'=>$userInfo]);
            return $r && $updateTokenRes ?
                auto_success($r, '更新成功') :
                auto_failure($r, '更新失败');
        } catch (\Exception $e) {
            return auto_failure($e->getMessage());
        }
    }

    /**
     * 图片上传
     * @param $image
     * @return array
     */
    private function base64ToImg($image, $dirName = 'images')
    {
        $imageName = "25220_".date("His",time())."_".rand(1111,9999).'.png';
        if (strstr($image,",")){
            $image = explode(',',$image);
            $image = $image[1];
        }

        $path = "/uploads/".$dirName."/".date("Ymd",time());
        if (!is_dir('./'.$path)){ //判断目录是否存在 不存在就创建
            mkdir('./'.$path,0777,true);
        }
        $imageSrc=  $path."/". $imageName;  //图片名字

        $r = file_put_contents(ROOT_PATH ."public/".$imageSrc, base64_decode($image));//返回的是字节数
        return $r ?
            auto_success(['path' => $imageSrc]):
            auto_failure($r);
    }

    /**
     * 根据手机号获取短信验证码
     * @param $data
     * @return array
     */
    public function getVerifyByPhone($data, $isChangePhone = false)
    {
        if ($isChangePhone) {
            //检测手机号是否存在
            $res = User::where('phone', $data['mobile'])->first();
            if(!$res)
                return auto_failure(null, '该用户不存在');
        }
        $rand = rand(100000, 999999);
        $str = $data['token'].SMS;
        $res = self::set($str, $rand, SMS_EXPIRE_TIME);
        $signName = "三咖音乐";
        $template = "SMS_150860113";
        $param = json_encode(array(
            "code"=>$rand,
        ),JSON_UNESCAPED_UNICODE);
        $sendRes = $this->sendSms($data['mobile'], $signName, $template, $param);

        $sendRes = json_decode($sendRes,true);
        if($sendRes['Code'] != "OK")
            auto_failure($res, '发送失败');

        return $res ?
            auto_success($res, '发送成功') :
            auto_failure($res, '发送失败');
    }

    /**
     * 验证短信验证码
     * @param $data
     */
    public function verifySms($data)
    {
        $str = $data['token'].SMS;
        $oldSms = self::get($str);
        if(!$oldSms)
            return auto_failure(null, '短信验证码失效');
        if($data['sms'] != $oldSms)
            return auto_failure(null, '短信验证码不正确');
        Redis::del($str);
        return auto_success(true, '短信验证成功');
    }

    /**
     * 验证新手机号短信验证码并执行换绑
     * @param $data
     */
    public function changePhone($data)
    {
        $str = $data['token'].SMS;
        $sms = self::get($str);
        if(!$sms)
            return auto_failure(null, '短信验证码失效');

        if($data['sms'] != $sms)
            return auto_failure(null, '短信验证码不正确');
        Redis::del($str);

        $userMod = User::where(['id' => $data['user_id'], 'phone' => $data['old_mobile']])->first();
        if(!$userMod)
            return auto_failure(null, '旧手机号不正确');
        $userMod->phone = $data['mobile'];

        $this->changeRedisInfo($data['token'], $userMod->toArray());

        try {
            $res = $userMod->save();
            return $res ?
                auto_success($res, '换绑成功') :
                auto_failure($res, '换绑失败');
        } catch (\Exception $e) {
            return auto_failure($e->getMessage());
        }
    }

    /**
     * 签到
     * @param $data
     */
    public function sign($data)
    {
        $token = $data['token'];
        unset($data['token']);
        $data['created_at'] = date('Y-m-d H:i:s', NOW);
        $data['updated_at'] = date('Y-m-d H:i:s', NOW);
        $checkRes = $this->is_sign($data);
        if($checkRes['status'] == SUCCESS_STATUS)
            return auto_failure(null, '您已签到');

        DB::beginTransaction();
        try {
            $r1 = Signs::insert($data);

            //加积分
            $integralSetting = SettingIndex::SettingCategory()->getSelection(['action' => 'integralSetting']);
            $signInt = $integralSetting['sign'][0];
            $integralMod = IntegralAccount::where(['user_id' => $data['user_id']])->first();
            $integralMod->total = $integralMod->total + $signInt;
            $integralMod->income = $integralMod->income + $signInt;
            $integralMod->available_integral = $integralMod->available_integral + $signInt;
            $r2 = $integralMod->save();

            //添加积分操作日志
            $logData = [
                'user_id' => $data['user_id'],
                'type' => 'add',
                'integral' => $signInt,
                'total' => $integralMod->total,
                'income' => $integralMod->income,
                'available_integral' => $integralMod->available_integral,
                'expend' => $integralMod->expend,
                'freeze' => $integralMod->freeze,
                'remark' => '签到成功赠送'.$signInt.'积分',
                'create_time' => NOW,
                'update_time' => NOW,
            ];
            $r3 = IntegralOptionLog::insert($logData);

            if ($r1 && $r2 && $r3) {
                $tokenObj = new TokenLogic();
                $redisInfo = $tokenObj->hGetAll($token);
                $fundEtc = json_decode($redisInfo['res']['fund_etc'], true);
                $fundEtc['is_sign'] = true;
                $redisInfo['res']['fund_etc'] = json_encode($fundEtc, true);
                $tokenObj->hMset(['token'=>$token, 'arr'=>$redisInfo['res']]);
                DB::commit();
                return auto_success(null, '签到成功');
            }else{
                DB::rollBack();
                return auto_failure(null, '签到失败');
            }
        } catch (\Exception $e) {
            DB::rollBack();
            return auto_failure($e->getMessage(), '签到失败');
        }
    }

    /**
     * 根据id获取对方用户详情
     * @param $data
     */
    public function getInfoById($data)
    {
        $info = User::where(['id' => $data['id']])
            ->select('wechat', 'qq', 'phone', 'head_portrait', 'real_name', 'release_num', 'receive_num')
            ->first()
            ->toArray();
        $info['tags'] = (new CommentLogic())->getCommentStatistics(['user_id' => $data['id']])['res'];
        return auto_return($info);
    }

    /**
     * 检测用户是否签到
     * @param $data
     */
    public function is_sign($data)
    {
        $res = Signs::where('user_id', $data['user_id'])->whereDate('created_at', date('Y-m-d'))->first();
        return $res ?
            auto_success(true, '您已签到') :
            auto_failure(false, '未签到');
    }

    /**
     * 将数据存储至redis
     * @param $key
     * @param $value
     * @param int $expire
     * @return mixed
     */
    static private function set($key, $value, $expire = 30)
    {
        $res = Redis::set($key, $value);
        Redis::expire($key, $expire);
        return $res;
    }

    //将数据从redis中取出
    static private function get($key)
    {
        $res = Redis::get($key);
        return $res;
    }

    /**
     * 更新redis里面的用户信息
     */
    public function changeRedisInfo($token, $userInfo)
    {
        //更新redis存储的用户信息
        $tokenObj = new TokenLogic();
        $oldInfo = $tokenObj->hGetAll($token);
        $userInfo['fund_etc'] = $oldInfo['res']['fund_etc'];
        $updateTokenRes = $tokenObj->hMset(['token'=>$token, 'arr'=>$userInfo]);
        return $updateTokenRes;
    }

    /**
     * 用户信息
     */
    public function getUserByPhone($data)
    {
        $user = User::withCount(['car'=>function($query){ $query->where('is_del',0); }])->where('phone',$data['phone'])->where('name',$data['name'])->get();
        if($user->isEmpty()){
            return auto_failure($user,'没有此用户或用户名电话错误');
        }
        $arr = explode(',',$user[0]->role_ids);
        if(!in_array(164,$arr)){
            return auto_failure($arr,'该用户角色不是司机');
        }
        $company = CompanyDriver::where('driver_id',$user[0]->id)->where('status','<>',3)->get();
        if(!$company->isEmpty()){
            return auto_failure($company,'此用户已绑定');
        }
        return auto_success($user,'查找成功');
    }

    /**
     * 验证短信验证码并重置登录密码（忘记密码）
     * @param $data
     * @return array
     */
    public function changeLoginPwd($data)
    {
        if($data['login_pwd'] != $data['re_login_pwd'])
            return auto_failure(false, '登录密码和重复密码不一致');
        $str = $data['token'].SMS;
        $sms = self::get($str);
        if(!$sms)
            return auto_failure(null, '短信验证码失效');

        if($data['code'] != $sms)
            return auto_failure(null, '短信验证码不正确');
        //检测用户是否存在
        $checkRes = User::where('phone', $data['phone'])->first();
        if(!$checkRes)
            return auto_failure($checkRes, '该用户不存在');

        // 修改登录密码
        $newData = $this->_makeLoginPassword($data['login_pwd']);
        $_where = make_map($data, ['name','id','phone']);
        $_where['status'] = '1';
        $res = User::where($_where)->update($newData);
        return $res ?
            auto_success($res, '重置密码成功') :
            auto_failure($res, '重置密码失败');
    }

    /**
     * 验证短信验证码并重置支付密码
     * @param $data
     * @return array
     */
    public function resetPayPassword($data)
    {
        if($data['pay_pass'] != $data['sure_pay_pass'])
            return auto_failure(false, '登录密码和重复密码不一致');
        $str = $data['token'].SMS;
        $sms = self::get($str);
        if(!$sms)
            return auto_failure(null, '短信验证码失效');

        if($data['code'] != $sms)
            return auto_failure(null, '短信验证码不正确');
        $payPasswordArr = $this->_makePayPassword($data['pay_pass']);
        $_where = make_map($data, ['name','id','phone']);
        $res = User::where($_where)
            ->update($payPasswordArr);
        return $res ?
            auto_success(true, '支付密码重置成功') :
            auto_failure(false, '重置支付密码失败');
    }
}
